<template>
  <div class="view-edit">
    <!-- 默认表单形式 -->
    <a-form
      v-bind="formConfig"
      ref="formRef"
      :model="formState"
      @finish="onFinish"
      @finishFailed="onFinishFailed"

    >
      <a-row v-bind="rowConfig">
        <a-col
          v-for="(item, index) in configJsonArr"
          :key="item.name"
          :span="grid === -1?grid:item.span?(24/grid)*item.span:24/grid"
          v-bind="colConfig"
        >
          <a-form-item v-bind="item">
            <template v-if="!isEdit || item.changeFromItem === false">
              <slot :name="item.name">
                <span>
                  {{formatTextValue(item)}}
                </span>
              </slot>
            </template>
            <template v-else-if="item.type === 'a-upload'">
              <a-upload
                :fileList="formState[item.name]"
                v-bind="item"
                :beforeUpload="(file, fileList)=>handleBeforeUpload(file, fileList, item)"
                @remove="(file)=> handleRemove(file, item)"
              >
                <a-button>
                  <upload-outlined></upload-outlined>
                  {{item.placeholder || '上传文件'}}
                </a-button>
              </a-upload>
            </template>
            <component
              v-else
              :is="item.type"
              v-bind="item.props"
              v-model:value="formState[item.name]"
              @change="(e)=>handleChange(e, item)"
              :filter-option="(input, option)=>filterOption(input, option, item)"
            >

            </component>
          </a-form-item>
        </a-col>
        <a-col v-if="footer">
          <slot name="footer">
            <edit-save-button :isEdit="isEdit" @edit="handleEditSaveButtonClick('edit')" @cancel="handleEditSaveButtonClick('cancel')" @save="handleEditSaveButtonClick('save')"></edit-save-button>
          </slot>
        </a-col>
      </a-row>
    </a-form>
  </div>
</template>

<script setup>
import {UploadOutlined} from '@ant-design/icons-vue';
import EditSaveButton from "../EditSaveButton"
import { ref, defineProps, computed, watch, nextTick, defineExpose, defineEmits, onMounted } from "vue";
const props = defineProps({
  formConfig: {
    type: Object,
    default: ()=> ({
      autocomplete:"off"
    })
  },
  rowConfig: {
    type: Object,
    default: ()=> {}
  },
  colConfig: {
    type: Object,
    default: ()=> {}
  },
  configJsonArr: {
    type: Array,
    default: ()=> []
  },
  baseData: {
    type: Object,
    default: ()=> {}
  },
  // grid 24的约数
  grid: {
    type: Number,
    default: -1
  },
  isEdit: {
    type: Boolean,
    default: true
  },
  footer: {
    type: Boolean,
    default: false
  }
})
const _$emit = defineEmits(['confirm', 'reset', 'watchItem','edit', 'cancel', 'save'])


//自定义节点 label、value、options 的字段
const fieldNames = {label: 'label', value: 'value', children: 'children',options:'options'};
// 通过 值 在数组对象中查询对应的label
const findLabel = (options=[], value, valueName='value', labelName='label')=> {
  if(options && options.length) {
    return options.find(item => item[valueName] === value)[labelName] || '';
  }
}

watch(()=> props.isEdit, (newVal)=> {
  if(!newVal) {
    // 如果切换到详情，需要把清除校验
    formRef.value.clearValidate();
  }
  if(currentEditSaveButtonClickType) {
    // 使用内部设置的切换按钮 点击取消走这里
    if(currentEditSaveButtonClickType === 'cancel') {
      showOriginFormState()
    }
  }
  if(newVal) {
    // 设置原始值
    originFormState = {...formState.value}
  }
})

// 数据回显
watch(() => props.baseData,(newVal)=> {
  nextTick(()=> {
    // 初始化值，否则每项都必须在baseData里存在
    let obj = {}
    props.configJsonArr.forEach(item => {
      if(item.type == 'a-upload') {
        // 上传回显
        obj = {...obj, [item.name]: item.fileList || [] }
      }else {
        obj = {...obj, [item.name]: undefined}
      }
    })
    formState.value = {...obj,...newVal}
  })
},{
  immediate: true,
  deep: true
})

let originFormState = {};//存储每次编辑前的数据
let currentEditSaveButtonClickType = ''//edit cancel save
onMounted(()=> {
  nextTick(()=> {
    originFormState = {...formState.value}
  })
})

// 内部切换按钮
const handleEditSaveButtonClick = (type)=> {

  currentEditSaveButtonClickType = type
  _$emit(type)
}
const formRef = ref()
const formState = ref({})

// 监听表单变化
const handleChange = (e,item) => {
  if(item.watch) {
    _$emit('watchItem', {
      method: item.watchMethod,
      name: item.name,
      value: e?.target?.value || e
    })
  }
}
// 中文名称（详情展示）统一特殊处理
const  formatTextValue = computed(()=> {
  return (item)=> {
    let {type, name, props, showValue} = item
    let textValue = ''
    if(formState.value[name]=== undefined) {
      // 在formState数据没有成功赋值之前，全部默认为展示空字符串，否则会报错
      return textValue
    }
    if(showValue) {
      textValue = formState.value[showValue]
      return textValue
    }
    switch(type) {
      case 'a-select':
      case 'a-radio-group':
        let selectValue = formState.value[name]
        if(!props.mode) {
          // 单选
          if(props.labelInValue) {
            selectValue = formState.value[name].value
          }
          if(props.fieldNames) {
            // 是否自定义 节点字段
            let {label, value} = props.fieldNames
            textValue = findLabel(props.options, selectValue, value, label)
          }else {
            textValue = findLabel(props.options, selectValue)
          }
        }else {
          textValue = formState.value[name]
        }
        break;
      case 'a-range-picker':
        textValue = formState.value[name].join('~')
        break;
      default:
          textValue = formState.value[name]
        break;
    }
    return textValue
  }
})
// select 搜索
const filterOption = (input, option, item)=> {
  let label = item.props.fieldNames['label']||'label'
  return option[label].indexOf(input) >= 0;
}
// 上传文件
const handleBeforeUpload = (file, fileList, item)=> {
  formState.value[item.name] = fileList
}
// 移除文件
const handleRemove = (file, item)=> {
  const index = formState.value[item.name].indexOf(file);
  const newFileList = formState.value[item.name].slice();
  newFileList.splice(index, 1);
  formState.value[item.name] = newFileList;
}
const onFinish = (values) => {
  _$emit('confirm', values)
};

const onFinishFailed = (values,errorInfo) => {
  console.log('Failed:', errorInfo);
  _$emit('confirm', values)
};


/**获取值表单事件  */
const getAllValues = async ()=> {
  try {
    let values = await formRef.value.validateFields()
    return values
  }catch(error) {
    console.error(`submit error: ${error}`)
  }
}
/**重置表单事件  */
const onReset = (status = false) => {
  formRef.value.resetFields()

  if (status) {
    _$emit('reset')
  }
}

/**展示编辑前的值 点击取消时使用 父组件必须使用此方法才能达到取消效果*/
const showOriginFormState = ()=> {
  // 如果点击取消，详情的值跟原来编辑前一致
  formState.value = {...originFormState}
}

/** 暴露外部使用方法 */
defineExpose({
  onReset,
  getAllValues,
  showOriginFormState
})
</script>

<style lang="less" scoped>
.view-edit {
  .width120 {
    width: 120px;
  }
  .bg-color-pink,.bg-color-green {
    border: 1px solid rebeccapurple;
    text-align: center;
    line-height: 30px;
    height: 30px;
  }
  .bg-color-pink {
    background: pink;
  }
  .bg-color-green {
    background: greenyellow;
  }
}
</style>
